package parser

import (
	"encoding/json"
	"fmt"
	"github.com/pkg/errors"
	"learn/smart/fetcher"
	"learn/smart/parser/c5game/store"
	"strconv"
	"strings"
	"learn/smart/util/redis"
	"time"
	"learn/smart/parser/c5game/history"
)

type OriginItem struct {
	OriginName string
	Name       string
	ExtraPrice float64
	IsExtra    bool
}

type ISellResult struct {
	D_List []ISellItem
	Succ   bool
}

type ISellItem struct {
	Name       string
	Unit_Price string
	Product_Id int
	Id         int
}

func GetOriginItem(name string) (OriginItem) {
	oi := OriginItem{Name: name, IsExtra: false}

	if strings.Index(name, "亲笔签名") == 0 {
		oi.IsExtra = true
		oi.OriginName = strings.Replace(name, "亲笔签名", "", -1)
		oi.ExtraPrice = 3
	}

	if strings.Index(name, "铭刻") == 0 {
		oi.IsExtra = true
		oi.OriginName = strings.Replace(name, "铭刻", "", -1)
		oi.ExtraPrice = 1.6
	}

	if strings.Index(name, "冥灵") == 0 {
		oi.IsExtra = true
		oi.OriginName = strings.Replace(name, "冥灵", "", -1)
		oi.ExtraPrice = 10
	}

	oi.OriginName = strings.TrimSpace(oi.OriginName)

	return oi
}

func GetLowestPriceByName(name string) (float64, error) {
	cachePrice := GetLowestPriceFromCache(name)

	if cachePrice <= 0 {
		return GetLowestPriceFromStore(name)
	}

	return cachePrice, nil
}

func GetLowestPriceFromStore(name string) (float64, error) {
	var price float64

	item, err := FindItemFromStore(name)

	if err != nil {
		return price, err
	}
	price = item.Price
	if price <= 0 {
		return price, errors.New(fmt.Sprintf("未找到Name: %s", name))
	}
	//save to redis
	client := redis.GetClient()
	client.HSet(getLowestPriceKey(), name, price)
	client.Expire(getLowestPriceKey(), 24*time.Hour)
	return price, nil
}

func FindItemFromStore(name string) (store.Item, error) {
	var item store.Item

	sItems, err := store.Search(name, 570)

	if err != nil {
		return item, err
	}

	for _, sItem := range sItems {
		if strings.Compare(strings.TrimSpace(sItem.Name), name) == 0 &&
			strings.Compare(sItem.Product_Type, "S") == 0 {
			item = sItem
			break
		}
	}

	return item, nil
}

func getLowestPriceKey() string {
	return time.Now().Format("2006-01-02")
}

func GetLowestPriceFromCache(name string) (float64) {
	client := redis.GetClient()
	result, err := client.HGet(getLowestPriceKey(), name).Result()
	if err != nil {
		return 0
	}
	price, err := strconv.ParseFloat(result, 64)

	if err != nil {
		return 0
	}

	return price
}

var igxeOnSellRateLimiter = time.Tick(10 * time.Millisecond)

// get igxe on sell lowest price item info
func GetIgxeOnSellLowestItem(pId int) (ISellItem, error) {
	<-igxeOnSellRateLimiter
	f := fetcher.Fetcher{BaseUrl: "https://www.igxe.cn"}

	path := fmt.Sprintf("/product/trade/570/%d?gem_id=0&page_no=1&gem_attribute_id=0&status_locked=0", pId)
	resp, err := f.Get(path, nil)
	var lowest ISellItem
	if err != nil {
		return lowest, err
	}
	defer resp.Body.Close()

	contents, err := fetcher.GetContents(resp)
	if err != nil {
		return lowest, err
	}

	var result ISellResult
	json.Unmarshal(contents, &result)

	if result.Succ == false {
		return lowest, errors.New("请求返回Succ: false")
	}

	if len(result.D_List) == 0 {
		return lowest, errors.New("没有找到任何饰品信息")
	}

	lowest = result.D_List[0]

	return lowest, nil
}

func GetLowestPriceFromHistory(name string) (float64, error) {
	var price float64

	price = GetLowestHistoryPriceFromCache(name)

	if price <= 0 {
		item, err := FindItemFromStore(name)

		if err != nil {
			return price, err
		}

		price = history.GetMedianPrice(item.Item_Id)
		if price > 0 {
			//save to redis
			client := redis.GetClient()
			client.HSet(GetLowestHistoryKey(), name, price)
			client.Expire(GetLowestHistoryKey(), 2*time.Hour)
		} else {
			msg := fmt.Sprintf("获取 %s 历史记录有误", name)
			return 0, errors.New(msg)
		}
	}

	return price, nil
}

func GetLowestHistoryPriceFromCache(name string) float64 {
	client := redis.GetClient()
	result, err := client.HGet(GetLowestHistoryKey(), name).Result()

	if err != nil {
		return 0
	}

	price, err := strconv.ParseFloat(result, 64)
	if err != nil {
		return 0
	}

	return price
}

func GetLowestHistoryKey() string {
	index := time.Now().Hour() + time.Now().Hour()%2
	i := strconv.Itoa(index)
	return time.Now().Format("2006-01-02") + ".history.median." + i
}
